﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Xml.Serialization;

namespace BDSim
{
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class StationClock
    {
        #region 字段
        private StationBase _Parent;
        private UTCTimeClass _Clk_t0 = new UTCTimeClass();
        private double _Clk_b0 = 4.30072529611428e-004;
        private double _Clk_d0 = 1.826384e-012;
        private double _Clk_r0 = 1.0e-018;
        private double _Clk_NoiseH;
        private double _Clk_tao = 30;

        /// <summary>
        /// 卫星钟差值，单位为秒（s）
        /// </summary>
        [XmlIgnore]
        public double Clk_Err;
        /// <summary>
        /// 整步点钟差输出
        /// </summary>
        [XmlIgnore]
        public AtomicClockErr StepClkErr;
        [XmlIgnore]
        public SimParam simParam;       //系统时间，包括初始时间，系统运行步长、步数
        private ClkErr_Input clkErr_Input;
        private ClkErr_Output clkErr_Output;
        private ClkTrp_Input clkTrp_Input;
        private ClkTrp_Param clkTrp_Param;
        private ClkTrp_Output clkTrp_Output;
        #endregion


        #region 属性
  
        [Browsable(false), XmlIgnore]
        public StationBase Parent
        {
            get { return _Parent; }
            set { _Parent = value;}
        }

        /// <summary>
        /// 对应的初始钟差历元
        /// </summary>
        [XmlIgnore, Browsable(false), CategoryAttribute("钟差参数"), DescriptionAttribute("初始钟差历元"), PropertyOrder(0)]
        public UTCTimeClass Clk_t0
        {
            get { return _Clk_t0; }
            set { _Clk_t0 = value;}
        }

        /// <summary>
        /// 初始钟差，单位s
        /// </summary>
        [XmlAttribute, CategoryAttribute("钟差参数"), DescriptionAttribute("钟差"), PropertyOrder(1)]
        public double Clk_b0
        {
            get { return _Clk_b0; }
            set
            {
                if (value > 10e-3 || value < -10e-3)
                {
                    MessageBox.Show("初始钟差设置应在[-10e-3,10e-3]s之间!");
                }
                else
                {
                    _Clk_b0 = value;
                }
            }
        }

        /// <summary>
        /// 初始钟漂，单位s/s
        /// </summary>
        [XmlAttribute, CategoryAttribute("钟差参数"), DescriptionAttribute("初始钟漂（频移）"), PropertyOrder(2)]
        public double Clk_d0
        {
            get { return _Clk_d0; }
            set
            {
                if (value > 10e-9 || value < -10e-9)
                {
                    MessageBox.Show("初始钟漂设置应在[-10e-9,10e-9]s/s之间!");
                }
                else
                {
                    _Clk_d0 = value;
                }

            }
        }

        /// <summary>
        /// 初始钟速，单位s/s²
        /// </summary>
        [XmlAttribute, CategoryAttribute("钟差参数"), DescriptionAttribute("初始钟速（老化率）"), PropertyOrder(3)]
        public double Clk_r0
        {
            get { return _Clk_r0; }
            set
            {
                if (value > 10e-15 || value < -10e-15)
                {
                    MessageBox.Show("初始钟速设置应在[-10e-15,10e-15]s/s2之间!");
                }
                else
                {
                    _Clk_r0 = value;
                }
            }
        }

        /// <summary>
        /// 钟噪声
        /// </summary>
        [XmlAttribute, CategoryAttribute("钟差参数"), DescriptionAttribute("初始钟差噪声强度"), PropertyOrder(4)]
        public double Clk_NoiseH
        {
            get { return _Clk_NoiseH; }
            set
            {
                if (value > 2 * 10e-9 || value < -2 * 10e-9)
                {
                    MessageBox.Show("钟噪声量级设置应在[-2*10e-9,2*10e-9]s之间!");
                }
                else
                {
                    _Clk_NoiseH = value;
                }
            }
        }

        /// <summary>
        /// 钟差采样时间间隔，单位为秒（s）
        /// </summary>
        [XmlAttribute, CategoryAttribute("钟差参数"), DescriptionAttribute("钟差采样时间间隔，单位为秒（s）"), PropertyOrder(4)]
        public double Clk_tao
        {
            get { return _Clk_tao; }
            set
            {
                if (value > 0)
                {
                    _Clk_tao = value;
                }
                else
                    MessageBox.Show("钟差采样时间间隔必须大于0！");
            }
        }

        #endregion


        #region 方法

        /// <summary>
        /// 地面站钟初始化
        /// </summary>
        public void Init()
        {
            simParam = Parent.simParam;
            clkErr_Input.TimeId = 0;

            clkErr_Input.clk.m_b0 = _Clk_b0;
            clkErr_Input.clk.m_d0 = _Clk_d0;
            clkErr_Input.clk.m_a = _Clk_r0;
            clkErr_Input.clk.m_tao = _Clk_tao;
            clkErr_Input.clk.m_H = new double[4] { 0, 0, 0, 0 };
            clkErr_Input.addNoise = 1;
            clkErr_Input.H = new double[2];
            clkErr_Input.H[0] = _Clk_NoiseH;
            CClkSimDLL.ClockErr_Output(simParam, clkErr_Input, out clkErr_Output);
            StepClkErr = clkErr_Output.clkerr;//五步点
            RealOut(StepClkErr);
        }

        /// <summary>
        /// 地面站钟整步点仿真
        /// </summary>
        public void FixedStepOut()
        {
            double nowtime = simParam.simClks * ((double)simParam.simStepInt) * 1e-6;
            int TimeId = 0;
            TimeId = Convert.ToInt32(Math.Floor((nowtime + 0.001) / (clkErr_Input.clk.m_tao)));
            int nStep = Convert.ToInt32(TimeId - clkErr_Input.TimeId);
            for (int i = 0; i < nStep; i++)
            {
                clkErr_Input.TimeId = TimeId;
                CClkSimDLL.ClockErr_Output(simParam, clkErr_Input, out clkErr_Output);
                StepClkErr = clkErr_Output.clkerr;//为外部观测数据生成提供钟差数据
                StepClkErr.m_TimeId = TimeId;
            }
        }

        /// <summary>
        /// 地面站钟实时仿真
        /// </summary>
        public void RealOut(AtomicClockErr clkErr)
        {
            double nowtime = simParam.simClks * ((double)simParam.simStepInt) * 1e-6;
            int TimeId = 0;
            TimeId = Convert.ToInt32(Math.Floor((nowtime) / (clkErr_Input.clk.m_tao)));
            //实时计算钟差
            clkTrp_Input.tobs = nowtime;
            clkTrp_Input.a = new double[7];
            clkTrp_Input.a[0] = TimeId;
            clkTrp_Input.a[1] = clkErr_Input.clk.m_tao;
            clkTrp_Input.a[2] = clkErr.m_sb2;
            clkTrp_Input.a[3] = clkErr.m_sb1;
            clkTrp_Input.a[4] = clkErr.m_s0;
            clkTrp_Input.a[5] = clkErr.m_sa1;
            clkTrp_Input.a[6] = clkErr.m_sa2;
            clkTrp_Param.Iclo = 1;
            CClkSimDLL.ClockErr_Trp(clkTrp_Input, clkTrp_Param, out clkTrp_Output);
            Clk_Err = clkTrp_Output.DeltClock;//实时计算钟差
        }

        public override string ToString()
        {
            return string.Empty;
        }

        #endregion

    }
}

